package com.woniuxy01;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 作者
 * @create 2025-09-23 17:14
 * 封装JDBC的操作
 */
public class JdbcUtil {
    //创建连接对象
    public static Connection getConnection() throws SQLException, ClassNotFoundException {
        String className="com.mysql.cj.jdbc.Driver";
        String url="jdbc:mysql://localhost:3306/db3";
        String user="root";
        String password="123";
        Class.forName(className);
        return DriverManager.getConnection(url, user, password);
    }

    public static void close(Connection conn, Statement stmt, ResultSet rs) throws SQLException {
        if(rs != null) {
            rs.close();
        }
        if(stmt != null) {
            stmt.close();
        }
        if(conn != null) {
            conn.close();
        }
    }

    //封装添加删除修改的操作
    public static int update(Connection connection,String sql,Object... params) throws SQLException {
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        if(params!=null){
            for(int i=0;i<params.length;i++){
                preparedStatement.setObject(i+1,params[i]);
            }
        }
        int count = preparedStatement.executeUpdate();
        close(connection,preparedStatement,null);
        return count;
    }

    //封装查询操作,返回值:实体类对象或者集合
    //项目中一个表对应一个实体类,我们希望要一个通用的方法，支持任意类型,反射实现
    public static <T> List<T> queryList(Connection connection, Class<T> clazz ,String sql, Object... params) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        List<T> list=new ArrayList<T>();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        if(params!=null){
            for(int i=0;i<params.length;i++){
                preparedStatement.setObject(i+1,params[i]);
            }
        }
        ResultSet resultSet = preparedStatement.executeQuery();
        //获取元数据:元数据中可以获取数据库列名
        ResultSetMetaData metaData = resultSet.getMetaData();
        while(resultSet.next()){
            //读取每行数据，读取一行创建一个T的对象
            T t = clazz.newInstance();
            //给对象的属性赋值:后面我们学得框架默认规则:实例类的属性名和表中的列(字段)名一样
            for(int i=0;i<metaData.getColumnCount();i++){
                //获取每列的名字
                String columnName = metaData.getColumnName(i + 1);
                //根据列名获取实体类的属性
                Field field = clazz.getDeclaredField(columnName);
                //使用反射给字段赋值=该列的值
                field.setAccessible(true);
                field.set(t,resultSet.getObject(columnName));
            }
            list.add(t);
        }
        close(connection,preparedStatement,resultSet);
        return list;
    }

    public static <T> T queryOne(Connection connection, Class<T> clazz ,String sql, Object... params) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        T t = clazz.newInstance();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        if(params!=null){
            for(int i=0;i<params.length;i++){
                preparedStatement.setObject(i+1,params[i]);
            }
        }
        ResultSet resultSet = preparedStatement.executeQuery();
        //获取元数据:元数据中可以获取数据库列名
        ResultSetMetaData metaData = resultSet.getMetaData();
        if(resultSet.next()){
            //读取每行数据，读取一行创建一个T的对象
            //给对象的属性赋值:后面我们学得框架默认规则:实例类的属性名和表中的列(字段)名一样
            for(int i=0;i<metaData.getColumnCount();i++){
                //获取每列的名字
                String columnName = metaData.getColumnName(i + 1);
                //根据列名获取实体类的属性
                Field field = clazz.getDeclaredField(columnName);
                //使用反射给字段赋值=该列的值
                field.setAccessible(true);
                field.set(t,resultSet.getObject(columnName));
            }
        }
        close(connection,preparedStatement,resultSet);
        return t;
    }
}
